<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram - Rolling Sphere</title>
</head>
<body>

<canvas id="physicsCanvas" width="600" height="500" style="border:1px solid #000;"></canvas>

<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // Helper function to draw an arrow
    function drawArrow(ctx, fromx, fromy, tox, toy, text = null) {
        const headlen = 10; // length of head in pixels
        const dx = tox - fromx;
        const dy = toy - fromy;
        const angle = Math.atan2(dy, dx);

        ctx.beginPath();
        ctx.moveTo(fromx, fromy);
        ctx.lineTo(tox, toy);
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
        ctx.stroke();
    }
    
    // Drawing parameters
    const cx = 300; // Center X of the large cylinder
    const cy = 350; // Center Y of the large cylinder
    const R = 180;  // Radius of the large cylinder
    const r = 40;   // Radius of the small sphere
    const phi = Math.PI / 4.5; // Angle phi, about 40 degrees

    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2;

    // --- 1. Draw Large Cylinder Arc ---
    ctx.beginPath();
    ctx.arc(cx, cy, R, 1.2 * Math.PI, 1.8 * Math.PI);
    ctx.stroke();
    
    // Label O
    ctx.font = 'italic 20px Times New Roman';
    ctx.fillText('O', cx, cy + 20);

    // --- 2. Draw Initial Sphere at the top ---
    const topSphereX = cx;
    const topSphereY = cy - R - r;
    ctx.beginPath();
    ctx.arc(topSphereX, topSphereY, r, 0, 2 * Math.PI);
    ctx.stroke();

    // Label m and r for the initial sphere
    ctx.fillText('m', topSphereX, topSphereY - r - 15);
    ctx.beginPath();
    ctx.setLineDash([5, 3]);
    ctx.moveTo(topSphereX, topSphereY);
    ctx.lineTo(topSphereX, topSphereY + r);
    ctx.stroke();
    ctx.setLineDash([]);
    ctx.fillText('r', topSphereX + 15, topSphereY + r/2);

    // Label μ
    ctx.fillText('μ', cx + 40, cy - R + 20);


    // --- 3. Draw Rolled Sphere ---
    const sphereCenterX = cx + (R + r) * Math.sin(phi);
    const sphereCenterY = cy - (R + r) * Math.cos(phi);

    ctx.beginPath();
    ctx.arc(sphereCenterX, sphereCenterY, r, 0, 2 * Math.PI);
    ctx.stroke();

    // --- 4. Draw Forces and Vectors ---
    // mg (Gravity)
    const mg_len = 80;
    drawArrow(ctx, sphereCenterX, sphereCenterY, sphereCenterX, sphereCenterY + mg_len);
    ctx.fillText('mg', sphereCenterX + 25, sphereCenterY + mg_len/2);
    
    // N (Normal Force)
    const N_len = 70;
    const N_endX = sphereCenterX + N_len * Math.sin(phi);
    const N_endY = sphereCenterY - N_len * Math.cos(phi);
    drawArrow(ctx, sphereCenterX, sphereCenterY, N_endX, N_endY);
    ctx.fillText('N', N_endX + 5, N_endY - 15);
    
    // v_C (Velocity)
    const vC_len = 70;
    // Velocity is tangent to the path of the center of mass (circle of radius R+r)
    const vC_angle = Math.PI/2 + phi;
    const vC_endX = sphereCenterX + vC_len * Math.cos(vC_angle - Math.PI/2);
    const vC_endY = sphereCenterY + vC_len * Math.sin(vC_angle - Math.PI/2);
    drawArrow(ctx, sphereCenterX, sphereCenterY, vC_endX, vC_endY);
    ctx.font = 'italic 20px Times New Roman';
    ctx.fillText('v', vC_endX + 10, vC_endY + 10);
    ctx.font = 'italic 14px Times New Roman';
    ctx.fillText('C', vC_endX + 18, vC_endY + 15);

    // f (Friction)
    const f_len = 60;
    const contactX = cx + R * Math.sin(phi);
    const contactY = cy - R * Math.cos(phi);
    // Friction is tangent to the surface, pointing "up the slope"
    const f_angle = phi - Math.PI/2;
    const f_endX = contactX - f_len * Math.cos(f_angle + Math.PI/2);
    const f_endY = contactY - f_len * Math.sin(f_angle + Math.PI/2);
    drawArrow(ctx, contactX, contactY, f_endX, f_endY);
    ctx.font = 'italic 20px Times New Roman';
    ctx.fillText('f', f_endX - 20, f_endY - 5);

    // ω (Angular Velocity)
    ctx.beginPath();
    ctx.arc(sphereCenterX, sphereCenterY, r * 0.5, 0.2 * Math.PI, 1.5 * Math.PI);
    ctx.stroke();
    // Arrowhead for ω
    const omega_arrow_angle = 1.5 * Math.PI;
    const omega_arrow_x = sphereCenterX + r * 0.5 * Math.cos(omega_arrow_angle);
    const omega_arrow_y = sphereCenterY + r * 0.5 * Math.sin(omega_arrow_angle);
    const omega_headlen = 8;
    ctx.beginPath();
    ctx.moveTo(omega_arrow_x, omega_arrow_y);
    ctx.lineTo(omega_arrow_x - omega_headlen * Math.cos(omega_arrow_angle - Math.PI/2 - Math.PI / 6), omega_arrow_y - omega_headlen * Math.sin(omega_arrow_angle - Math.PI/2 - Math.PI / 6));
    ctx.stroke();
    ctx.fillText('ω', sphereCenterX + r * 0.5 + 10, sphereCenterY);

    // --- 5. Draw Dashed Lines and Angle ---
    ctx.setLineDash([5, 5]);
    // Vertical line for R
    ctx.beginPath();
    ctx.moveTo(cx, cy);
    ctx.lineTo(cx, cy - R);
    ctx.stroke();
    ctx.fillText('R', cx - 20, cy - R / 2);

    // Radial line to rolled sphere
    ctx.beginPath();
    ctx.moveTo(cx, cy);
    ctx.lineTo(sphereCenterX, sphereCenterY);
    ctx.stroke();

    // Angle φ
    ctx.beginPath();
    ctx.arc(cx, cy, 40, -Math.PI/2, -Math.PI/2 + phi);
    ctx.stroke();
    ctx.setLineDash([]);
    const phi_label_x = cx + 50 * Math.sin(phi / 2);
    const phi_label_y = cy - 50 * Math.cos(phi / 2);
    ctx.fillText('φ', phi_label_x, phi_label_y);

    // --- 6. Draw Caption ---
    ctx.font = '20px "Songti SC", "SimSun", serif';
    ctx.fillText('力图 6.13.1', cx, cy + 100);

</script>

</body>
</html>